package com.decent;

import cn.hutool.core.collection.CollUtil;
import com.decent.common.config.DecentSystemConfig;
import com.decent.common.xss.XssFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.Resource;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * web模块启动类
 *
 * @author decent
 **/
@SpringBootApplication
@EnableAspectJAutoProxy
public class WebApplication {
    @Resource
    private ApplicationContext applicationContext;
    @Resource
    private DecentSystemConfig decentSystemConfig;

    static {
        System.setProperty("druid.mysql.usePingMethod","false");
    }

    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }

    /**
     * 注册xss过滤器
     *
     * @return xss过滤器
     */
    @Bean(name = "XssFilter")
    public FilterRegistrationBean<XssFilter> xssFilterRegistration() {
        FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
        DecentSystemConfig.XssConfig xssConfig = decentSystemConfig.getXssConfig();
        registration.setFilter(new XssFilter(xssConfig.getXssProtectLevel()));
        Set<String> allSaveUrlPattern = allUrlMappings();
        if (CollUtil.isEmpty(allSaveUrlPattern)) {
            return registration;
        }
        Set<String> urlPatterns = allSaveUrlPattern.stream()
                .filter(url -> !Pattern.matches(xssConfig.getExcludeXssPatterns(), url))
                .collect(Collectors.toCollection(LinkedHashSet::new));
        registration.setUrlPatterns(urlPatterns);
        registration.setName("XssFilter");
        registration.setOrder(1);
        return registration;
    }

    /**
     * 获取容器中所有路径
     *
     * @return set
     */
    private Set<String> allUrlMappings() {
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        return map.keySet().stream().map(keyInfo -> Objects.requireNonNull(keyInfo.getPatternsCondition()).toString().replace("[", "").replace("]", ""))
                .collect(Collectors.toSet());
    }
}
